package com.lizardmind.haofudoctor.other

import com.blankj.utilcode.util.EncodeUtils
import com.blankj.utilcode.util.EncryptUtils
import com.google.gson.JsonObject
import com.linxiao.framework.net.StringResponseBody
import com.linxiao.framework.util.AESUtils
import com.linxiao.framework.util.RSAUtils
import com.linxiao.framework.util.ke
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.Interceptor
import okhttp3.Response
import okio.Buffer
import org.json.JSONArray
import org.json.JSONObject
import java.io.EOFException
import java.nio.charset.Charset
import java.nio.charset.UnsupportedCharsetException

/**
 *
 * Created by Extends on 2017/10/25 15:25
 * TODO:参数有Base64时，禁止用android.util.Base64
 */
class EncryptInterceptor: Interceptor {
    private val TAG = "EncryptInterceptor"
    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()
        //动态生成key
        val key = AESUtils.generateKey()
        //取出请求的参数
        val cs = getRequestKey(request)
        //把参数和key进行md5校验
        val md5 = EncryptUtils.encryptMD5ToString(cs+key)
        //把生成的密钥通过公钥加密，输入为经过Base64加密后的字符串
        val k1 = RSAUtils.encryptByPublicKey(key)
        //把参数和MD5校验值通过密钥加密
        val k2=AESUtils.encrypt((cs+md5).toByteArray(),key.toByteArray())
        //重新构建新的request
        request = request.newBuilder()
                .post(FormBody.Builder()
                        .add("key1",k1)
                        .add("key2",EncodeUtils.base64Encode2String(k2))
                        .build())
                .build()
//        ke(cs,key,getRequestKey(request))
        val response = chain.proceed(request)
        //获取服务器返回的数据
        val jo = JSONObject(getResponBodyString(response)!!)
        //如果状态值不是成功就原样返回
        if(jo.getInt("status") != 200){
            return response
        }
        //把data取出来的值结果Base64解密后再通过密钥解密
        val d = String(AESUtils.decrypt(EncodeUtils.base64Decode(jo.getString("data")),key.toByteArray())!!)
        val i = d.length -32
        //校验值前面的原始数据
        val q = d.substring(0,i)
        //校验值
        val new_md5 = d.substring(i)
//        ke(q,new_md5)
        //判断数据是否校验成功
        if(EncryptUtils.encryptMD5ToString(q+key)==new_md5.toUpperCase()){
            when(q[0]){
                '{'->jo.put("data",JSONObject(q))
                '['->jo.put("data",JSONArray(q))
                'n','N'->jo.put("data",null)
                else->jo.put("data",q)
            }
        }else{
            jo.put("status",300)
            jo.put("data",null)
        }
        return response.newBuilder()
                .body(StringResponseBody(jo.toString()))
                .build()
    }

    private val UTF8 = Charset.forName("UTF-8")

    private fun bodyEncoded(headers: Headers): Boolean {
        val contentEncoding = headers.get("Content-Encoding")
        return contentEncoding != null && !contentEncoding.equals("identity", ignoreCase = true)
    }

    @Throws(EOFException::class)
    fun isPlaintext(buffer: Buffer): Boolean {
        try {
            val prefix = Buffer()
            val byteCount = (if (buffer.size() < 64) buffer.size() else 64).toLong()
            buffer.copyTo(prefix, 0, byteCount)
            for (i in 0..15) {
                if (prefix.exhausted()) {
                    break
                }
                val codePoint = prefix.readUtf8CodePoint()
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false
                }
            }
            return true
        } catch (e: EOFException) {
            return false // Truncated UTF-8 sequence.
        }
    }

    /**
     * 获取request的参数,用来作为缓存文件的name
     */
    fun getRequestKey(request: okhttp3.Request):String{
        return EncodeUtils.urlDecode(when(request.method()){
            "GET"->{
                request.url().toString()
            }
            "POST"->{
                val requestBody = request.body()
                val jo = JsonObject()
                if(requestBody is FormBody){
                    for (i in 0 until requestBody.size()){
                        jo.addProperty(requestBody.encodedName(i),requestBody.encodedValue(i))
                    }
                    jo.toString()
                }else{
                    //TODO:其他类型的body暂不考虑
                    "null"
                }
            }
            else->"null"
        })
    }

    /**
     * 获取respon的数据
     */
    fun getResponBodyString(response: Response):String?{
        val responseBody = response.body()
        if(responseBody!=null){
            val contentLength = responseBody.contentLength()
            if (!bodyEncoded(response.headers())) {
                val source = responseBody.source()
                source.request(java.lang.Long.MAX_VALUE) // Buffer the entire body.
                val buffer = source.buffer()

                var charset = UTF8
                val contentType = responseBody.contentType()
                if (contentType != null) {
                    try {
                        charset = contentType.charset(UTF8)
                    } catch (e: UnsupportedCharsetException) {
                        return null
                    }
                }

                if (!isPlaintext(buffer)) {
                    return null
                }

                if (contentLength != 0L) {
                    val result = buffer.clone().readString(charset)
                    return result
                }
            }
        }
        return null
    }
}